package com.cskaoyan.javase.recursion._0introduction;

/**
 * 我们已经学习过方法，使用过方法了。方法体中是可以调用方法的，那么如果在方法体中调用方法自身呢？
 *
 * 特别的，在一个方法当中再次调用这个方法，就像故事里提到同样的故事一样，我们把方法在运行时调用自身的情况，称之为递归，又叫做递归调用。
 *
 * 递归的使用:
 *      1.首先递归必须在方法中,写语句去调用自身.这一条调用自身的语句,称之为"递归体"
 *          要写递归,必然需要递归体
 *      2.如果一个递归,仅有递归体,肯定会导致方法"只进栈不出栈",导致栈溢出错误
 *          所以递归调用必须指明结束递归的条件
 *          称之为"递归的出口"
 *          一个正常的递归,必须要有递归的出口,否者必然报错.
 *          以上,递归体和递归的出口,称之为递归的两要素,一个正常的递归必然具有这两个东西.
 *
 *      3.有递归体,有递归出口,那么这个递归就是绝对安全的吗?
 *      不是这样的,还需要考虑递归的深度,如果递归的深度超过了栈内存大小,仍然会栈溢出.
 *
 * 所以,总结来说,递归是一种非常危险的解决问题的手段,稍有不慎就会栈溢出
 *      一般来说,在开发中,要尽量避免使用递归.
 *
 *
 * @since 16:45
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        System.out.println(sum(20000));
        /*
            分析:
            sum(10) = 10 + sum(9);
            sum(9) = 9 + sum(8);
            sum(8) = 8 + sum(7);
            ....
            这个过程显然不能自己主动停止
            请问这个程序的执行结果是什么?
                1.死循环
                2.程序报错了
                3.程序运行着,电脑爆炸了
            通过运行代码发现,程序报错终止,并且抛出异常"StackOverflowError"
            "栈溢出错误"
            这个异常是Error级别的错误,相对于Exception,它更严重

            为什么程序会抛出"StackOverflowError"呢?
            stack是栈的意思,指的是什么栈? JVM栈,JVM栈内存不够用了,产生了栈溢出
            因为方法只进栈不出栈,导致栈溢出
         */
    }

    // Method 'sum()' recurses infinitely, and can only end by throwing an exception
    public static int sum(int num) {
        // 递归的出口
        if (num == 0) {
            return 0;
        }
        // 在方法中自己调用自己,就是递归调用
        return num + sum(num - 1);
    }
}
